package ma.ensao.action;

import japa.parser.JavaParser;

import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.body.BodyDeclaration;
import japa.parser.ast.body.FieldDeclaration;
import japa.parser.ast.body.MethodDeclaration;
import japa.parser.ast.body.TypeDeclaration;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;


import com.opensymphony.xwork2.ActionSupport;

public class FileAction extends ActionSupport {
	
	private Pojo bean=new Pojo();
	private Description description;
	private File fileUpload;
	private String selectedPack="";
	private String selectedClass="";
	
	HashMap<String, Description> classes = new HashMap<>();
	HashMap<String, List<String>> paquetages = new HashMap<String, List<String>>();
	
	public String upload() throws ZipException, IOException{
		
		ZipFile zf = new ZipFile(fileUpload);
		Enumeration<? extends ZipEntry> zipFileEntries = zf.entries();// projet
		
		// Process each entry
				while (zipFileEntries.hasMoreElements()) {
					// grab a zip file entry
					ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();// element suivant

					if (!entry.isDirectory()) {
						// ********************traitement sur les fichiers *.java
						// contenu dans le rep scr************************
						BufferedInputStream is = new BufferedInputStream(
								zf.getInputStream(entry));

						CompilationUnit cu;
						try {
							// parse the file
							cu = JavaParser.parse(is);
							traitement(cu);

						} catch (ParseException e) {

							e.printStackTrace();
						} finally {
							is.close();
						}
					
					}
				}
				
				bean.setClasse(classes);
				bean.setPaquetage(paquetages);
			
			    for(Entry<String,List<String>> packag : bean.getPaquetage().entrySet()) {
					String cle = packag.getKey();
					bean.getListPackage().add(cle);
					}
		return "SUCCESS";
	}
	
	public String affichageClasse(){
		
		bean.setListClasse(bean.getPaquetage().get(selectedPack.trim()));
		return "SUCCESS";
	}

	public String descriptionClass(){
		description=bean.getClasse().get(selectedClass);
		return "SUCCESS";
	}

	private void traitement(CompilationUnit cu) {

		// liste des classes contenu dans un package
		List<String> listeClasses = new ArrayList<String>();

		List<TypeDeclaration> types = cu.getTypes();// toutes les classes
		
		// Debut: Rempliassage des classes et leurs descriptions dans le bean
		for (TypeDeclaration type : types) {// classe par classe

			// Debut: Rempliassage des packages et leurs classes dans le bean
			 
			 String[] nomPack=cu.getPackage().toString().split(" ")[1].split(";");
			 if(paquetages.containsKey(nomPack[0])){
			 paquetages.get(nomPack[0]).add(type.getName().toString());
			 }
			
			 else{
			 listeClasses.add(type.getName());
			 paquetages.put(nomPack[0], listeClasses);
			 }
			// ****

			Description desc = new Description();
			// remplissage du nom du package
			List<BodyDeclaration> members = type.getMembers();// tous les champs
																// d'une classe
																// attributs et
																// methods

			for (BodyDeclaration member : members) {// champs par champs

				if (member instanceof MethodDeclaration) {
					MethodDeclaration method = (MethodDeclaration) member;

					String fonction = method.toString();
					// extraire la signature de la classe
					String s = "";
					for (int i = 0; i < fonction.length(); i++) {
						if (s.length() < fonction.indexOf("{"))
							s += fonction.substring(i, i + 1);
					}
					// *********Methode extraite*************
					// System.out.println("Methode de classe "+s);
					if(s.contains("private"))
						desc.getMethodePrivate().add(s.substring(8));
					else if(s.contains("public"))
						desc.getMethodePublic().add(s.substring(7));
					else if(s.contains("protected"))
						desc.getMethodeProtected().add(s.substring(10));
					

				}
				if (member instanceof FieldDeclaration) {
					FieldDeclaration field = (FieldDeclaration) member;

					String[] att1 = field.toString().split("=");
					String[] att2 = att1[0].split(";");

					// *********attributs extrait*************
					// System.out.println("attributs de classe "+att2[0]);
					if(att2[0].contains("private"))
						desc.getAttributPrivate().add(att2[0].substring(8));
					else if(att2[0].contains("public"))
						desc.getAttributPublic().add(att2[0].substring(7));
					else if(att2[0].contains("protected"))
						desc.getAttributProtected().add(att2[0].substring(10));

				}
			}
			// rassembler des classes
			classes.put(type.getName(), desc);
		}
	}


	public Pojo getBean() {
		return bean;
	}


	public void setBean(Pojo bean) {
		this.bean = bean;
	}


	public Description getDescription() {
		return description;
	}


	public void setDescription(Description description) {
		this.description = description;
	}


	public File getFileUpload() {
		return fileUpload;
	}


	public void setFileUpload(File fileUpload) {
		this.fileUpload = fileUpload;
	}



	public String getSelectedPack() {
		return selectedPack;
	}

	public void setSelectedPack(String selectedPack) {
		this.selectedPack = selectedPack;
	}

	public String getSelectedClass() {
		return selectedClass;
	}

	public void setSelectedClass(String selectedClass) {
		this.selectedClass = selectedClass;
	}


	
}
